/*
 * 
 *  This file is part of Sourceprojects.org Lycia Copyright 2010 noctarius
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 */
package org.sourceprojects.lycia.internal;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * A special implementation of {@link InputStream} that prebuffers the data to
 * be handled internally and to get the data's length.
 * 
 * @author noctarius
 * @since 1.9.1
 */
public class PrebufferedInputStream extends InputStream implements DataLength {
	private final ByteArrayInputStream byteArrayInputStream;
	private final long length;

	public PrebufferedInputStream(final InputStream inputStream)
			throws IOException {
		int read = -1;
		byte[] buffer = new byte[0x10000];
		final ByteArrayOutputStream output = new ByteArrayOutputStream();
		while ((read = inputStream.read(buffer, 0, buffer.length)) >= 0) {
			output.write(buffer, 0, read);
		}

		buffer = output.toByteArray();
		length = buffer.length;
		byteArrayInputStream = new ByteArrayInputStream(buffer);
	}

	@Override
	public int available() throws IOException {
		return byteArrayInputStream.available();
	}

	@Override
	public void close() throws IOException {
		byteArrayInputStream.close();
	}

	@Override
	public synchronized void mark(final int readlimit) {
		byteArrayInputStream.mark(readlimit);
	}

	@Override
	public boolean markSupported() {
		return byteArrayInputStream.markSupported();
	}

	@Override
	public int read() throws IOException {
		return byteArrayInputStream.read();
	}

	@Override
	public int read(final byte[] b, final int off, final int len)
			throws IOException {
		return byteArrayInputStream.read(b, off, len);
	}

	@Override
	public int read(final byte[] b) throws IOException {
		return byteArrayInputStream.read(b);
	}

	@Override
	public synchronized void reset() throws IOException {
		byteArrayInputStream.reset();
	}

	@Override
	public long skip(final long n) throws IOException {
		return byteArrayInputStream.skip(n);
	}

	@Override
	public long length() {
		return length;
	}

}
